package com.tobby.camelinaction.client;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import org.apache.camel.Exchange;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.spi.Synchronization;
import org.apache.camel.support.SynchronizationAdapter;
import org.apache.camel.test.junit4.CamelTestSupport;
import org.junit.Test;

public class CamelCallBackTest extends CamelTestSupport {

	@Override
	protected RouteBuilder createRouteBuilder() throws Exception {
		return new RouteBuilder() {

			@Override
			public void configure() throws Exception {
				// this is the route we want to send message to in an async manner.
				// usually the route is something that takes some time to do
				from("seda:echo?concurrentConsumers=5").log("Starting to  route ${body}").delay(3000).transform()
						.simple("${body}${body}").log("Route is now done");
			}
		};
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Test
	public void testCamelCallBack() throws Exception {
		// echos is the list of replies which could be modified by multiple thread
		final List<String> echos = new CopyOnWriteArrayList<String>();
		final CountDownLatch latch = new CountDownLatch(5);

		// use this callback to gather the replies and add it to the echos list
		Synchronization callback = new SynchronizationAdapter() {
			@Override
			public void onDone(Exchange exchange) {
				// get the reply and add it to echos
				echos.add(exchange.getOut().getBody(String.class));
				// count down latch when we receive a response
				latch.countDown();
			}
		};

		// now shutdonw 3 async request/reply messages and use the same callback to handle the replies
		template.asyncCallbackRequestBody("seda:echo", "Donkey", callback);
		template.asyncCallbackRequestBody("seda:echo", "Tiger", callback);
		template.asyncCallbackRequestBody("seda:echo", "Camel", callback);

		// wait until the messages is done, or timeout after 6 seconds
		latch.await(6, TimeUnit.SECONDS);

		// assert we got 3 replies
		assertEquals(3, echos.size());
		List result = new ArrayList<>(echos);

		// sort list so we can assert by index
		Collections.sort(result);
		assertEquals("CamelCamel", result.get(0));
		assertEquals("DonkeyDonkey", result.get(1));
		assertEquals("TigerTiger", result.get(2));
	}
}
